package roborally.Pieces;

import be.kuleuven.cs.som.annotate.*;

/**
 * This is a class of GamePieces representing a repair kit with a certain amount of Energy.
 * @invar	the energy of a repairkit is never greater than its maximum Energy 
 * 			| RepairKit.getMaxEnergy().isGreaterThanOrEquals(this.getEnergy())
 * @version 3.0
 * @author Bart Opsomer 2de Bachelor Ingenieurswetenschappen Electrotechniek-Computerwetenschappen 
 * 		   Peter Opsomer 1ste Master Wiskundige IngenieursTechnieken
 */
public class RepairKit extends Item implements Energizerable {
	// The energy of this repairKit
	private Energy energy;
	//The maximum Energy of a ReapirKit, equal for all repairKits
	private static Energy maxEnergy = new Energy(Double.MAX_VALUE);
	
	/**
	 * Create a new RepairKit with the given energy and weight
	 * @param energy the energy of the RepairKit
	 * @param weight the weight of the RepairKit, expressed in grams
	 * @effect  | setEnergy(energy)
	 */
	public RepairKit(Energy energy, int weight) {
		super(weight);
		setEnergy(energy);
	}
	/**
	 * @return	return the current energy of this repairKit
	 */
	@Basic
	public Energy getEnergy() {
		return this.energy;
	}
	/**
	 * @return the maximum Energy of a RepairKit
	 */
	@Basic
	public static Energy getMaxEnergy() {
		return maxEnergy;
	}
	/**
	 * Set the energy to the given energy
	 * @pre RepairKit.maxEnergy.isGreaterThanOrEquals(newEnergy)
	 * @param newEnergy the energy to which the energy of this Repairkit is to be set
	 * @post 	the new Energy is set
	 * 			| new.getEnergy() == newEnergy
	 */
	private void setEnergy(Energy newEnergy) {
		assert(RepairKit.getMaxEnergy().isGreaterThanOrEquals(newEnergy));
		this.energy = newEnergy;
	}
	/**
	 * Overrides the default use-Method of Item. When a reapirKit is use by a robot, the repairKit uses an amount of its energy to repair
	 * the given robot, by increasing the maximum energy a robot can carry( = robot.getFullEnergy() ), as much as possible by half the amount the repairKit uses.
	 * The energy of the repairKit is decreased by the amount the repairkit uses.
	 * @param robot	the robot that uses this RepairKit
	 * @post	The energy used by the repairkit is half the fullEnergy increase of the robot
	 * 			| ( this.getEnergy().getAmountInWattSeconds() - new.getEnergy().getAmountInWattSeconds() )/2 
	 * 			|	= robot.getFullEnergy().getAmountInWattSeconds() - (new robot).getFullEnergy().getAmountInWattSeconds()
	 * @post	This repairkit's Energy is empty or the Robot is at its full Energy
	 * 			| this.getEnergy().compareTo(Energy.ZERO) == 0 || robot.getFullEnergy().compareTo(robot.getMaxEnergy() ) == 0
	 */
	@Override
	public void use(Robot robot) {
		if(robot == null) {
			return;	
		}
		// If the RepairKit the robot is trying to use is terminated, the RepairKit must be discarded by the robot
		if(this.isTerminated()) {
			robot.drop(this);
		}
		Energy temp = new Energy(robot.getFullEnergy());
		Energy energyOfRepairKit = this.getEnergy();
		Energy energyToRepair = new Energy( energyOfRepairKit.divide( new Energy(2) ) );
		temp.increase(energyToRepair);
		Energy leftOverEnergy = new Energy(0);
		Energy maxEnergyOfRobot = robot.getMaxEnergy();
		if(maxEnergyOfRobot.isGreaterThanOrEquals(temp)) {
			//Recharges completely
			robot.getFullEnergy().increase(energyToRepair);
			energyOfRepairKit.decrease(energyOfRepairKit);
			//Robot does not have to automatically drop RepairKits when they are empty
		}
		else {
			// Recharge the robot until fullEnergy
			temp.decrease(maxEnergyOfRobot);
			energyToRepair.decrease(temp);
			robot.getFullEnergy().increase(energyToRepair);
			leftOverEnergy = new Energy(temp.getAmountInWattSeconds()*2);
		}
		// This means setting the energy twice because also energyOfRepairKit.decrease(...), just to be sure
		this.setEnergy(leftOverEnergy);

	}
	/**
	 * Overrides the default shootThis-Method of Item.
	 * It increases the energy of this reapirKit by 500 Ws
	 * @post	if the current energy increased with 500 Ws is not greater than the maximum energy, 
	 * 			the current energy is increased with 500 Ws, else the current energy is set to to the maximum energy
	 * 			| if getMaximumEnergy.isGreaterThanOrEquals(this.getEnergy.increase(new Energy(500)) )
	 * 			| 	then new.getEnergy().getAmountInWattSeconds() = thsi.getEnergy().getAmountInWattSeconds() + 500
	 * 			|	else new.getEnergy() = this.getMaximumEnergy();
	 */
	@Override
	public void shootThis() {
		Energy nextEnergy = this.energy;
		nextEnergy.increase(new Energy(500));
		if(RepairKit.getMaxEnergy().isGreaterThanOrEquals(nextEnergy) ) {
			setEnergy(nextEnergy);
		}
		else{
			setEnergy(new Energy(RepairKit.getMaxEnergy()) );
		}
	}
	/**
	 * Return a textual representation of this Repairkit for the GUI. This method gives information about the energy, weight and then the position of the Repairkit.
	 * 
	 * @return | result.equals("Repairkit with energy " + energy.toString() + super.toString() )
	 */
	@Override
	public String toString() {
		return "Repairkit with energy " + energy.toString() + super.toString();
	}

}
